#include "pk11.h"
#include "pk11_const_macros.h"

#define MODULE_FOR_CONSTS cPKCS11
#define BASECLASS_FOR_ERRORS ePKCS11Error

static VALUE vOBJECT_CLASSES;
static VALUE vATTRIBUTES;
static VALUE vMECHANISMS;
static VALUE vRETURN_VALUES;

VALUE
pkcs11_return_value_to_class(CK_RV rv, VALUE ePKCS11Error)
{
  VALUE class;

  class = rb_hash_aref(vRETURN_VALUES, ULONG2NUM(rv));
  if (NIL_P(class)){
    class = ePKCS11Error;
  }

  return class;
}

void
Init_pkcs11_const(VALUE cPKCS11, VALUE ePKCS11Error)
{
  PKCS11_DEFINE_CONST(CRYPTOKI_VERSION_MAJOR);
  PKCS11_DEFINE_CONST(CRYPTOKI_VERSION_MINOR);
  PKCS11_DEFINE_CONST(CRYPTOKI_VERSION_AMENDMENT);

  /* General constant */
  PKCS11_DEFINE_CONST(CK_UNAVAILABLE_INFORMATION);
  PKCS11_DEFINE_CONST(CK_EFFECTIVELY_INFINITE);
  PKCS11_DEFINE_CONST(CK_INVALID_HANDLE);

  /* Notification */
  PKCS11_DEFINE_CONST(CKN_SURRENDER);

  /* Bit flag */
  PKCS11_DEFINE_CONST(CKF_TOKEN_PRESENT);
  PKCS11_DEFINE_CONST(CKF_REMOVABLE_DEVICE);
  PKCS11_DEFINE_CONST(CKF_HW_SLOT);
  PKCS11_DEFINE_CONST(CKF_RNG);
  PKCS11_DEFINE_CONST(CKF_WRITE_PROTECTED);
  PKCS11_DEFINE_CONST(CKF_LOGIN_REQUIRED);
  PKCS11_DEFINE_CONST(CKF_USER_PIN_INITIALIZED);
  PKCS11_DEFINE_CONST(CKF_RESTORE_KEY_NOT_NEEDED);
  PKCS11_DEFINE_CONST(CKF_CLOCK_ON_TOKEN);
  PKCS11_DEFINE_CONST(CKF_PROTECTED_AUTHENTICATION_PATH);
  PKCS11_DEFINE_CONST(CKF_DUAL_CRYPTO_OPERATIONS);
  PKCS11_DEFINE_CONST(CKF_TOKEN_INITIALIZED);
  PKCS11_DEFINE_CONST(CKF_SECONDARY_AUTHENTICATION);
  PKCS11_DEFINE_CONST(CKF_USER_PIN_COUNT_LOW);
  PKCS11_DEFINE_CONST(CKF_USER_PIN_FINAL_TRY);
  PKCS11_DEFINE_CONST(CKF_USER_PIN_LOCKED);
  PKCS11_DEFINE_CONST(CKF_USER_PIN_TO_BE_CHANGED);
  PKCS11_DEFINE_CONST(CKF_SO_PIN_COUNT_LOW);
  PKCS11_DEFINE_CONST(CKF_SO_PIN_FINAL_TRY);
  PKCS11_DEFINE_CONST(CKF_SO_PIN_LOCKED);
  PKCS11_DEFINE_CONST(CKF_SO_PIN_TO_BE_CHANGED);
  PKCS11_DEFINE_CONST(CKF_RW_SESSION);
  PKCS11_DEFINE_CONST(CKF_SERIAL_SESSION);
  PKCS11_DEFINE_CONST(CKF_LIBRARY_CANT_CREATE_OS_THREADS);
  PKCS11_DEFINE_CONST(CKF_OS_LOCKING_OK);
  PKCS11_DEFINE_CONST(CKF_DONT_BLOCK);
  PKCS11_DEFINE_CONST(CKF_HW);
  PKCS11_DEFINE_CONST(CKF_ENCRYPT);
  PKCS11_DEFINE_CONST(CKF_DECRYPT);
  PKCS11_DEFINE_CONST(CKF_DIGEST);
  PKCS11_DEFINE_CONST(CKF_SIGN);
  PKCS11_DEFINE_CONST(CKF_SIGN_RECOVER);
  PKCS11_DEFINE_CONST(CKF_VERIFY);
  PKCS11_DEFINE_CONST(CKF_VERIFY_RECOVER);
  PKCS11_DEFINE_CONST(CKF_GENERATE);
  PKCS11_DEFINE_CONST(CKF_GENERATE_KEY_PAIR);
  PKCS11_DEFINE_CONST(CKF_WRAP);
  PKCS11_DEFINE_CONST(CKF_UNWRAP);
  PKCS11_DEFINE_CONST(CKF_DERIVE);
  PKCS11_DEFINE_CONST(CKF_EC_F_P);
  PKCS11_DEFINE_CONST(CKF_EC_F_2M);
  PKCS11_DEFINE_CONST(CKF_EC_ECPARAMETERS);
  PKCS11_DEFINE_CONST(CKF_EC_NAMEDCURVE);
  PKCS11_DEFINE_CONST(CKF_EC_UNCOMPRESS);
  PKCS11_DEFINE_CONST(CKF_EC_COMPRESS);
  PKCS11_DEFINE_CONST(CKF_EXTENSION);
  PKCS11_DEFINE_CONST(CKF_ARRAY_ATTRIBUTE);
  PKCS11_DEFINE_CONST(CKF_EXCLUDE_CHALLENGE);
  PKCS11_DEFINE_CONST(CKF_EXCLUDE_COUNTER);
  PKCS11_DEFINE_CONST(CKF_EXCLUDE_PIN);
  PKCS11_DEFINE_CONST(CKF_EXCLUDE_TIME);
  PKCS11_DEFINE_CONST(CKF_NEXT_OTP);
  PKCS11_DEFINE_CONST(CKF_USER_FRIENDLY_OTP);

  /* User type */
  PKCS11_DEFINE_CONST(CKU_SO);
  PKCS11_DEFINE_CONST(CKU_USER);
  PKCS11_DEFINE_CONST(CKU_CONTEXT_SPECIFIC);

  /* Hardware feature type */
  PKCS11_DEFINE_CONST(CKH_MONOTONIC_COUNTER);
  PKCS11_DEFINE_CONST(CKH_CLOCK);
  PKCS11_DEFINE_CONST(CKH_USER_INTERFACE);
  PKCS11_DEFINE_CONST(CKH_VENDOR_DEFINED);

  /* Key type */
  PKCS11_DEFINE_CONST(CKK_RSA);
  PKCS11_DEFINE_CONST(CKK_DSA);
  PKCS11_DEFINE_CONST(CKK_DH);
  PKCS11_DEFINE_CONST(CKK_ECDSA);
  PKCS11_DEFINE_CONST(CKK_EC);
  PKCS11_DEFINE_CONST(CKK_X9_42_DH);
  PKCS11_DEFINE_CONST(CKK_KEA);
  PKCS11_DEFINE_CONST(CKK_GENERIC_SECRET);
  PKCS11_DEFINE_CONST(CKK_RC2);
  PKCS11_DEFINE_CONST(CKK_RC4);
  PKCS11_DEFINE_CONST(CKK_DES);
  PKCS11_DEFINE_CONST(CKK_DES2);
  PKCS11_DEFINE_CONST(CKK_DES3);
  PKCS11_DEFINE_CONST(CKK_CAST);
  PKCS11_DEFINE_CONST(CKK_CAST3);
  PKCS11_DEFINE_CONST(CKK_CAST5);
  PKCS11_DEFINE_CONST(CKK_CAST128);
  PKCS11_DEFINE_CONST(CKK_RC5);
  PKCS11_DEFINE_CONST(CKK_IDEA);
  PKCS11_DEFINE_CONST(CKK_SKIPJACK);
  PKCS11_DEFINE_CONST(CKK_BATON);
  PKCS11_DEFINE_CONST(CKK_JUNIPER);
  PKCS11_DEFINE_CONST(CKK_CDMF);
  PKCS11_DEFINE_CONST(CKK_AES);
  PKCS11_DEFINE_CONST(CKK_ACTI);
  PKCS11_DEFINE_CONST(CKK_ARIA);
  PKCS11_DEFINE_CONST(CKK_BLOWFISH);
  PKCS11_DEFINE_CONST(CKK_CAMELLIA);
  PKCS11_DEFINE_CONST(CKK_HOTP);
  PKCS11_DEFINE_CONST(CKK_SECURID);
  PKCS11_DEFINE_CONST(CKK_TWOFISH);
  PKCS11_DEFINE_CONST(CKK_VENDOR_DEFINED);

  /* Certificate type */
  PKCS11_DEFINE_CONST(CKC_X_509);
  PKCS11_DEFINE_CONST(CKC_X_509_ATTR_CERT);
  PKCS11_DEFINE_CONST(CKC_WTLS);
  PKCS11_DEFINE_CONST(CKC_VENDOR_DEFINED);

  /* Session state */
  PKCS11_DEFINE_CONST(CKS_RO_PUBLIC_SESSION);
  PKCS11_DEFINE_CONST(CKS_RO_USER_FUNCTIONS);
  PKCS11_DEFINE_CONST(CKS_RW_PUBLIC_SESSION);
  PKCS11_DEFINE_CONST(CKS_RW_USER_FUNCTIONS);
  PKCS11_DEFINE_CONST(CKS_RW_SO_FUNCTIONS);

  /* Mask generation function */
  PKCS11_DEFINE_CONST(CKG_MGF1_SHA1);
  PKCS11_DEFINE_CONST(CKG_MGF1_SHA224);
  PKCS11_DEFINE_CONST(CKG_MGF1_SHA256);
  PKCS11_DEFINE_CONST(CKG_MGF1_SHA384);
  PKCS11_DEFINE_CONST(CKG_MGF1_SHA512);

  /* Key delivation function */
  PKCS11_DEFINE_CONST(CKD_NULL);
  PKCS11_DEFINE_CONST(CKD_SHA1_KDF);
  PKCS11_DEFINE_CONST(CKD_SHA1_KDF_ASN1);
  PKCS11_DEFINE_CONST(CKD_SHA1_KDF_CONCATENATE);

  /* Pseudo-random function */
  PKCS11_DEFINE_CONST(CKP_PKCS5_PBKD2_HMAC_SHA1);

  /* Salt/Encoding parameter store */
  PKCS11_DEFINE_CONST(CKZ_DATA_SPECIFIED);
  PKCS11_DEFINE_CONST(CKZ_SALT_SPECIFIED);

  vOBJECT_CLASSES = rb_hash_new();
  vATTRIBUTES = rb_hash_new();
  vMECHANISMS = rb_hash_new();
  vRETURN_VALUES = rb_hash_new();
  rb_define_const(cPKCS11, "OBJECT_CLASSES", vOBJECT_CLASSES);
  rb_define_const(cPKCS11, "ATTRIBUTES", vATTRIBUTES);
  rb_define_const(cPKCS11, "MECHANISMS", vMECHANISMS);
  rb_define_const(cPKCS11, "RETURN_VALUES", vRETURN_VALUES);

  #include "pk11_const_def.inc"

  rb_obj_freeze(vOBJECT_CLASSES);
  rb_obj_freeze(vATTRIBUTES);
  rb_obj_freeze(vMECHANISMS);
  rb_obj_freeze(vRETURN_VALUES);

  /* OTP parameters */
  PKCS11_DEFINE_CONST(CK_OTP_CHALLENGE);
  PKCS11_DEFINE_CONST(CK_OTP_COUNTER);
  PKCS11_DEFINE_CONST(CK_OTP_FLAGS);
  PKCS11_DEFINE_CONST(CK_OTP_FORMAT_ALPHANUMERIC);
  PKCS11_DEFINE_CONST(CK_OTP_FORMAT_BINARY);
  PKCS11_DEFINE_CONST(CK_OTP_FORMAT_DECIMAL);
  PKCS11_DEFINE_CONST(CK_OTP_FORMAT_HEXADECIMAL);
  PKCS11_DEFINE_CONST(CK_OTP_OUTPUT_FORMAT);
  PKCS11_DEFINE_CONST(CK_OTP_OUTPUT_LENGTH);
  PKCS11_DEFINE_CONST(CK_OTP_PARAM_IGNORED);
  PKCS11_DEFINE_CONST(CK_OTP_PARAM_MANDATORY);
  PKCS11_DEFINE_CONST(CK_OTP_PARAM_OPTIONAL);
  PKCS11_DEFINE_CONST(CK_OTP_PIN);
  PKCS11_DEFINE_CONST(CK_OTP_TIME);
  PKCS11_DEFINE_CONST(CK_OTP_VALUE);
}
